import re
import pandas as pd
import json
import os
import sys
from tkinter import Tk, messagebox

def find_and_validate_files():
    """在EXE所在目录自动查找并验证所有必需的文件。"""
    try:
        if getattr(sys, 'frozen', False):
            application_path = os.path.dirname(sys.executable)
        else:
            application_path = os.path.dirname(os.path.abspath(__file__))
    except NameError:
        application_path = os.getcwd()

    error_messages = []
    excel_path, keywords_path = None, None
    json_paths = [] # 更改为列表

    all_files = os.listdir(application_path)
    
    # 1. Excel 文件 (保持不变)
    excel_files = [f for f in all_files if f.endswith('.xlsx') and not f.startswith('汇总结果')]
    if len(excel_files) == 0:
        error_messages.append("❌ 未找到 Excel 报告文件 (.xlsx)。")
    elif len(excel_files) > 1:
        error_messages.append(f"❌ 找到 {len(excel_files)} 个 Excel 文件，请只保留一个。")
    else:
        excel_path = os.path.join(application_path, excel_files[0])

    # 2. JSON 文件 (允许多个)
    json_files = [f for f in all_files if f.endswith('.json')]
    if len(json_files) == 0:
        error_messages.append("❌ 未找到数据文件 (.json)。")
    else:
        json_paths = [os.path.join(application_path, f) for f in json_files] # 获取所有JSON文件的路径

    # 3. 关键词文件 (保持不变)
    keywords_filename = 'keywords.txt'
    if keywords_filename not in all_files:
        error_messages.append(f"❌ 未找到关键词配置文件 ({keywords_filename})。")
    else:
        keywords_path = os.path.join(application_path, keywords_filename)
        
    return excel_path, json_paths, keywords_path, error_messages # 返回json_paths列表

def read_keywords_from_file(file_path):
    """从.txt文件中读取关键词列表，忽略空行。"""
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            lines = f.readlines()
            keywords = [line.strip() for line in lines if line.strip()]
        if not keywords:
            return None, "关键词文件 'keywords.txt' 是空的。"
        return keywords, None
    except Exception as e:
        return None, f"读取关键词文件失败：\n{e}"

def show_feedback_and_exit(message_type, title, message):
    """显示一个弹窗并退出程序。"""
    root = Tk()
    root.withdraw()
    root.attributes('-topmost', True)
    if message_type == 'error':
        messagebox.showerror(title, message)
    else:
        messagebox.showinfo(title, message)
    root.destroy()
    sys.exit()

def main():
    """主程序逻辑"""
    excel_file_path, json_file_paths, keywords_file_path, errors = find_and_validate_files() # 接收json_file_paths

    if errors:
        show_feedback_and_exit('error', "文件错误", "\n\n".join(errors) + "\n\n请修正文件后重试。")

    keywords, error = read_keywords_from_file(keywords_file_path)
    if error:
        show_feedback_and_exit('error', "文件错误", error)

    # --- 读取所有 JSON 文件并合并数据 ---
    all_channel_data_list = []
    for json_path in json_file_paths:
        try:
            with open(json_path, 'r', encoding='utf-8') as f:
                api_data = json.load(f)
                channel_data_list = api_data.get('data', {}).get('list', [])
                all_channel_data_list.extend(channel_data_list)
        except Exception as e:
            show_feedback_and_exit('error', "文件读取错误", f"读取 JSON 文件失败：\n{json_path}\n错误：{e}")

    # 继续处理Excel文件 (保持不变)
    try:
        df = pd.read_excel(excel_file_path)
    except Exception as e:
        show_feedback_and_exit('error', "文件读取错误", f"读取 Excel 文件失败：\n{excel_file_path}\n错误：{e}")

    # --- 数据处理与合并 ---
    channel_lookup = {}
    for item in all_channel_data_list:
        channel = item.get('channel')
        if channel:
            if channel not in channel_lookup:
                # 如果渠道不存在，直接添加所有项目
                channel_lookup[channel] = {k: v for k, v in item.items() if k != 'channel'}
                # 尝试将所有值转换为数字，如果转换失败则保留原始值
                for k, v in channel_lookup[channel].items():
                    try:
                        channel_lookup[channel][k] = int(v) if float(v) == int(float(v)) else float(v)
                    except (ValueError, TypeError):
                        pass # 转换失败，保留原始类型
            else:
                # 如果渠道已存在，合并数值型字段
                for key, value in item.items():
                    if key == 'channel':
                        continue # 跳过channel键
                    
                    try:
                        # 尝试将当前item中的value转换为数字
                        current_value_numeric = int(value) if float(value) == int(float(value)) else float(value)
                    except (ValueError, TypeError):
                        # 如果无法转换为数字，则保持原始值或跳过，取决于你的合并策略
                        # 这里我们选择如果不能转换为数字，就不进行加法合并，而是尝试更新或保留
                        if key not in channel_lookup[channel]: # 如果是新键，直接添加
                             channel_lookup[channel][key] = value
                        # 如果key已存在但不是数字，或者当前value也不是数字，这里需要更明确的策略
                        # 简单地讲，如果一个值不是数字，我们就不能把它加到另一个值上
                        continue 
                    
                    # 尝试将lookup中已有的值转换为数字
                    existing_value_in_lookup = channel_lookup[channel].get(key, 0) # 默认值0
                    try:
                        existing_value_numeric = int(existing_value_in_lookup) if float(existing_value_in_lookup) == int(float(existing_value_in_lookup)) else float(existing_value_in_lookup)
                    except (ValueError, TypeError):
                        # 如果lookup中已有的值也不是数字，则将其设置为当前value，或者采取其他策略
                        channel_lookup[channel][key] = current_value_numeric # 使用当前item的值覆盖
                        continue
                    
                    # 只有当两个值都是数字时才进行加法
                    channel_lookup[channel][key] = existing_value_numeric + current_value_numeric


    for col in ['已花费金额 (USD)', '展示次数', '点击量（全部）', '完成注册次数', '订阅次数']:
        if col in df.columns:
            df[col] = pd.to_numeric(df[col], errors='coerce').fillna(0)
    
    results = []
    for kw in keywords:
        regex_pattern = r'\b' + re.escape(kw) + r'\b'
        # mask = df['广告系列名称'].str.contains(kw, na=False, case=False)
        mask = df['广告系列名称'].str.contains(regex_pattern, na=False, case=False, regex=True)
        excel_data = df[mask]
        matched_channel_data = channel_lookup.get(kw, {})
        results.append({
            '': kw,
            '已花费金额 (USD)': excel_data['已花费金额 (USD)'].sum(),
            '展示次数': int(excel_data['展示次数'].sum()),
            '点击量（全部）': int(excel_data['点击量（全部）'].sum()),
            '完成注册次数': int(excel_data['完成注册次数'].sum()),
            '订阅次数': int(excel_data['订阅次数'].sum()),
            '新增用户': matched_channel_data.get('new_users', 0),
            '新增付费人数': matched_channel_data.get('newuser_charged', 0),
            '新增付费金额': matched_channel_data.get('newuser_charge_money', 0),
            '充值金额': matched_channel_data.get('charge_amount', 0),
            '提现金额': matched_channel_data.get('money_withdraw', 0)
        })
    result_df = pd.DataFrame(results)

    # --- 保存结果 (保持不变) ---
    output_dir = os.path.dirname(excel_file_path)
    output_file_path = os.path.join(output_dir, '汇总结果.xlsx')
    try:
        result_df.to_excel(output_file_path, index=False)
        show_feedback_and_exit('info', "成功", f"处理完成！\n结果已保存到：\n{output_file_path}")
    except Exception as e:
        show_feedback_and_exit('error', "保存失败", f"无法保存结果文件：\n{e}")

if __name__ == "__main__":
    main()